// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.chimi.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.BarPointBusinessEnum;
import com.liuxinlong.enums.BarStatusEnum;
import com.liuxinlong.enums.MessageContentTypeEnum;
import com.liuxinlong.enums.MessagePushBusinessEnum;
import com.liuxinlong.enums.NotificationSourceEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.chimi.dto.BarCommentDto;
import com.liuxinlong.modules.chimi.service.BarManageService;
import com.liuxinlong.modules.chimi.service.BarPointsService;
import com.liuxinlong.modules.dao.BarCardDao;
import com.liuxinlong.modules.dao.BarCommentDao;
import com.liuxinlong.modules.dao.BarPlateDao;
import com.liuxinlong.modules.dao.BarPointsFlowDao;
import com.liuxinlong.modules.dao.BarStatisticsDao;
import com.liuxinlong.modules.dao.FileManageDao;
import com.liuxinlong.modules.dao.MessageDao;
import com.liuxinlong.modules.dao.NotificationDao;
import com.liuxinlong.modules.dao.UserDao;
import com.liuxinlong.modules.dao.UserMatterDao;
import com.liuxinlong.modules.dao.UserThumbRecordDao;
import com.liuxinlong.modules.entity.BarCard;
import com.liuxinlong.modules.entity.BarComment;
import com.liuxinlong.modules.entity.BarStatistics;
import com.liuxinlong.modules.entity.MessageConfiguration;
import com.liuxinlong.modules.entity.Notification;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.entity.UserMatter;
import com.liuxinlong.modules.entity.UserThumbRecord;
import com.liuxinlong.modules.system.service.FileManageService;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.IPUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 论坛管理服务层接口实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022-07-07
 */
@Service
@Slf4j
public class BarManageServiceImpl implements BarManageService {
    @Autowired
    private BarCardDao barCardDao;

    @Autowired
    private BarPlateDao barPlateDao;

    @Autowired
    private BarCommentDao barCommentDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private BarStatisticsDao barStatisticsDao;

    @Autowired
    private FileManageService fileManageService;

    @Autowired
    private FileManageDao fileManageDao;

    @Autowired
    private NotificationDao notificationDao;

    @Autowired
    private UserMatterDao userMatterDao;

    @Autowired
    private MessageDao messageDao;

    @Autowired
    private BarPointsFlowDao barPointsFlowDao;

    @Autowired
    private UserThumbRecordDao userThumbRecordDao;

    @Autowired
    private BarPointsService barPointsService;

    @Override
    public List<Map<String, Object>> pageCard(Map<String, Object> queryParam) {
        int startNum = (int) queryParam.get("startNum");
        List<BarCard> originalList = barCardDao.pageBarCardManageList(queryParam);
        return completeResult(originalList, startNum);
    }

    @Override
    public int getCardCount(Map<String, Object> queryParam) {
        return barCardDao.getBarCardManageCount(queryParam);
    }

    @Override
    public void toppingCard(String id) {
        BarCard barCard = barCardDao.selectById(id);
        if (ObjectUtils.isEmpty(barCard)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "置顶状态修改失败，原帖信息不存在！");
        }
        int targetSort = barCard.getSortNum() == 99999 ? 1 : 99999;
        barCard.setSortNum(targetSort);
        barCardDao.updateById(barCard);
    }

    @Override
    public void updateCard(BarCard barCard) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        BarCard oldInfo = barCardDao.selectById(barCard.getId());
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "更新失败，原帖信息不存在！");
        }
        oldInfo.setTitle(barCard.getTitle());
        oldInfo.setPlate(barCard.getPlate());
        oldInfo.setReleaseType(barCard.getReleaseType());
        oldInfo.setCommentsHidden(barCard.getCommentsHidden());
        oldInfo.setCommentsModify(barCard.getCommentsModify());
        oldInfo.setContent(barCard.getContent());
        oldInfo.setUpdateUser(currentUser.getId());
        oldInfo.setUpdateTime(TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS));
        oldInfo.setAttach(barCard.getAttach());
        barCardDao.updateById(oldInfo);
        fileManageService.updateBusinessFile(barCard.getAttach(), barCard.getId());
    }

    @Override
    public void deleteCard(String id) {
        BarCard oldInfo = barCardDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除失败，原帖不存在！");
        }
        barCardDao.updateCardStatus(id, 3);
        fileManageDao.batchInvalidFile(id);
    }

    @Override
    @Transactional
    public void examineCard(String id, int result, String opinion, int syncMessage,int fineFlag) {
        barCardDao.updateCardStatus(id, result == 1 ? 1 : 2);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        User current = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        if (result == 1) {
            BarStatistics barStatistics = new BarStatistics();
            barStatistics.setId(id);
            barStatisticsDao.insert(barStatistics);
            BarCard cardInfo = barCardDao.selectById(id);
            if (syncMessage == 1) {
                User shareUser = userDao.selectById(cardInfo.getCreateUser());
                MessageConfiguration mc = new MessageConfiguration();
                mc.setId(SnowFlake.nextIdStr());
                mc.setBusinessType(MessagePushBusinessEnum.CHIMI.getValue());
                mc.setBusinessId(id);
                mc.setTitle(cardInfo.getTitle());
                mc.setCreateUser(current.getId());
                mc.setCreateTime(currentTime);
                mc.setPushType(2);
                mc.setContentType(MessageContentTypeEnum.TEXT_CARD.getValue());
                mc.setContent(cardInfo.getTitle());
                mc.setShareUser(shareUser.getName());
                mc.setTarget("3");
                messageDao.insert(mc);
            }
            if (fineFlag == 1) {
                barPointsService.updateUserPoints(cardInfo.getCreateUser(), BarPointBusinessEnum.POST_FINE.getValue(),0);
            } else {
                barPointsService.updateUserPoints(cardInfo.getCreateUser(), BarPointBusinessEnum.POST_COMMON.getValue(),0);
            }
        }
        UserMatter userMatter = userMatterDao.getBySourceId(id);
        if (!ObjectUtils.isEmpty(userMatter) && userMatter.getStatus() == 0) {
            userMatter.setDealUser(current.getId());
            userMatter.setDealTime(currentTime);
            userMatter.setStatus(1);
            userMatterDao.updateById(userMatter);
        }
    }

    @Override
    public List<Map<String, Object>> pageCardThumb(Map<String, Object> queryParam) {
        List<UserThumbRecord> originalList = userThumbRecordDao.pageUserThumbRecordList(queryParam);
        List<Map<String, Object>> dataList = new ArrayList<>(originalList.size());
        Map<String,Map<String,String>> userMap = userDao.getUserMap();
        int sort = (int)queryParam.get("startNum") + 1;
        for (UserThumbRecord record:originalList){
            Map<String,Object> item = ObjectUtils.object2Map(record);
            item.put("sort",sort);
            item.put("userName",userMap.containsKey(record.getUserId()) ? userMap.get(record.getUserId()).get("name") : "");
            dataList.add(item);
            sort++;
        }
        return dataList;
    }

    @Override
    public int getCardThumbCount(Map<String, Object> queryParam) {
        return userThumbRecordDao.getUserThumbRecordCount(queryParam);
    }

    @Override
    public List<Map<String, Object>> pageComment(Map<String, Object> queryParam) {
        List<BarCommentDto> originalList = barCommentDao.pageBarCommentManageList(queryParam);
        int startNum = (int) queryParam.get("startNum");
        List<Map<String, Object>> resultList = completeCommentResult(originalList, startNum);
        return resultList;
    }

    @Override
    public int getCommentCount(Map<String, Object> queryParam) {
        return barCommentDao.getBarCommentManageCount(queryParam);
    }

    @Override
    public void toppingComment(String id) {
        BarComment barComment = barCommentDao.selectById(id);
        if (ObjectUtils.isEmpty(barComment)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "置顶状态修改失败，原评论信息不存在！");
        }
        int targetSort = barComment.getSortNum() == 99999 ? 1 : 99999;
        barComment.setSortNum(targetSort);
        barCommentDao.updateById(barComment);
    }

    @Override
    public void updateComment(BarComment barComment) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        BarComment oldInfo = barCommentDao.selectById(barComment.getId());
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "更新失败，原评论信息不存在");
        }
        oldInfo.setAttach(barComment.getAttach());
        oldInfo.setContent(barComment.getContent());
        oldInfo.setUpdateUser(currentUser.getId());
        oldInfo.setUpdateTime(TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS));
        barCommentDao.updateById(oldInfo);
    }

    @Override
    public void deleteComment(String id) {
        BarComment oldInfo = barCommentDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除失败，原评论不存在！");
        }
        barCommentDao.updateCommentStatus(id, 3);
        fileManageDao.batchInvalidFile(id);
    }

    @Override
    public void examineComment(String id, int result) {
        BarComment barComment = barCommentDao.selectById(id);
        if (ObjectUtils.isEmpty(barComment)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "审核失败，评论信息不存在！");
        }
        BarCard barCard = barCardDao.selectById(barComment.getCardId());
        if (ObjectUtils.isEmpty(barCard)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "审核失败，原帖信息不存在！");
        }
        if (barCard.getStatus() != 1) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "审核失败，不能对非审核成功帖子评论！");
        }
        barCommentDao.updateCommentStatus(id, result == 1 ? 1 : 2);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        User current = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        if (result == 1) {
            BarStatistics barStatistics = new BarStatistics();
            barStatistics.setId(id);
            barStatisticsDao.insert(barStatistics);
            barStatisticsDao.addComments(barComment.getCardId());
            Notification notification = new Notification();
            notification.setId(SnowFlake.nextIdStr());
            notification.setCreateTime(currentTime);
            notification.setCreateUser(barComment.getCreateUser());
            notification.setSourceId(barComment.getCardId());
            User userInfo = userDao.selectById(barComment.getCreateUser());
            if (StringUtils.isNotEmpty(barComment.getReply())) {
                notification.setContent(userInfo.getName() + " 回复了你的评论 ");
                notification.setDealUser(barComment.getReplyUser());
                notification.setSourceType(NotificationSourceEnum.CHIMI_REPLY.getValue());
            } else {
                notification.setContent(userInfo.getName() + " 回复了你的发帖 " + barCard.getTitle());
                notification.setDealUser(barCard.getCreateUser());
                notification.setSourceType(NotificationSourceEnum.CHIMI_COMMENT.getValue());
            }
            notificationDao.insert(notification);
        }
        UserMatter userMatter = userMatterDao.getBySourceId(id);
        if (!ObjectUtils.isEmpty(userMatter) && userMatter.getStatus() == 0) {
            userMatter.setDealUser(current.getId());
            userMatter.setDealTime(currentTime);
            userMatter.setStatus(1);
            userMatterDao.updateById(userMatter);
        }
    }

    @Override
    public void exportCardInfo(Map<String, Object> queryParam,HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("用户发帖导出excel.xlsx");
        Map<String, Map<String, String>> plateMap = barPlateDao.getBarPlateMap();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
//        query.put("startTime", startTime);
        List<BarCard> cardList = barCardDao.getBarCardManageList(queryParam);
        String[] head = {"序号", "标题", "板块", "内容", "状态", "发布形式", "发帖人", "发帖人工号", "发帖时间", "修改人", "修改时间"};
        data.setHead(head);
        String[][] dataList = new String[cardList.size()][head.length];
        int index = 0;
        for (BarCard item : cardList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = item.getTitle();
            dataList[index][2] = plateMap.containsKey(item.getPlate()) ? plateMap.get(item.getPlate()).get("name") : "--";
            dataList[index][3] = item.getContent();
            dataList[index][4] = BarStatusEnum.getNameByValue(item.getStatus());
            dataList[index][5] = item.getReleaseType() == 1 ? "私密" : "公开";
            dataList[index][6] = userMap.containsKey(item.getCreateUser()) ? userMap.get(item.getCreateUser()).get("name") : "--";
            dataList[index][7] = userMap.containsKey(item.getCreateUser()) ? userMap.get(item.getCreateUser()).get("sn") : "--";
            dataList[index][8] = item.getCreateTime();
            dataList[index][9] = userMap.containsKey(item.getUpdateUser()) ? userMap.get(item.getUpdateUser()).get("name") : "--";
            dataList[index][10] = item.getUpdateTime();
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    public void exportCommentInfo(Map<String, Object> queryParam,HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("用户评论导出excel.xlsx");
        queryParam.put("startNum", 0);
        queryParam.put("pageSize", 10000);
        List<BarCommentDto> commentList = barCommentDao.pageBarCommentManageList(queryParam);
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        Map<String,Map<String,String>> cardMap = barCardDao.getBarCardMap();
        String[] head = {"序号", "帖子信息", "评论内容", "状态", "评论用户", "用户工号", "评论时间", "修改时间"};
        data.setHead(head);
        String[][] dataList = new String[commentList.size()][head.length];
        int index = 0;
        for (BarCommentDto item : commentList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = cardMap.containsKey(item.getCardId()) ? cardMap.get(item.getCardId()).get("title") : "";
            dataList[index][2] = item.getContent();
            dataList[index][3] = item.getStatus() == 0 ? "待审核" : item.getStatus() == 1 ? "审核通过" : "其他";
            dataList[index][4] = userMap.containsKey(item.getCreateUser()) ? userMap.get(item.getCreateUser()).get("name") : "";
            dataList[index][5] = userMap.containsKey(item.getCreateUser()) ? userMap.get(item.getCreateUser()).get("sn") : "--";
            dataList[index][6] = item.getCreateTime();
            dataList[index][7] = item.getUpdateTime();
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    /**
     * 数据补全转换
     *
     * @param originList 原始数据列表
     * @param startNum   起始查询数
     * @return 补全数据
     */
    private List<Map<String, Object>> completeResult(List<BarCard> originList, int startNum) {
        if (ObjectUtils.isEmpty(originList)) {
            return new ArrayList<>();
        }
        List<Map<String, Object>> resultList = new ArrayList<>(originList.size());
        String fileIds = StringUtils.strip(originList.stream().map(BarCard::getAttach).collect(Collectors.toSet()).toString().replaceAll(" ", "").replaceAll(",null", "").replaceAll(",,", ","), "[]");

        Set<String> fileIdList = new HashSet<>(Arrays.asList(fileIds.trim().split(",")));
        Map<String, Map<String, Object>> fileMap = new HashMap<>();
        if (!ObjectUtils.isEmpty(fileIdList)) {
            fileMap = fileManageDao.getFileMapByIds(fileIdList);
        }
        String currentIp = IPUtils.getCurrentIp();
        Map<String, Map<String, String>> plateMap = barPlateDao.getBarPlateMap();
        int sort = startNum + 1;
        for (BarCard record : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(record);
            map.put("sort", sort);
            User user = userDao.selectById(record.getCreateUser());
//            map.put("userPic", user.getPortrait());
            map.put("userName", user.getName());
            map.put("statusName", BarStatusEnum.getNameByValue(record.getStatus()));
            if (plateMap.containsKey(record.getPlate())) {
                Map<String, String> plateInfo = plateMap.get(record.getPlate());
                map.put("plateName", plateInfo.get("name"));
            }
            if (StringUtils.isNotEmpty(record.getAttach())) {
                List<String> cardFileList = Arrays.asList(record.getAttach().split(","));
                List<Map<String, Object>> fileList = new ArrayList<>(cardFileList.size());
                int fileSort = 1;
                for (String fileId : cardFileList) {
                    if (!fileMap.containsKey(fileId.trim())) {
                        continue;
                    }
                    Map<String, Object> fileInfo = new HashMap<>();
                    fileInfo.put("sort", fileSort);
                    fileInfo.put("id", fileId.trim());
                    fileInfo.put("path", String.valueOf(fileMap.get(fileId.trim()).get("path")).replace("upload", "http:\\\\" + currentIp + ":8090\\preview\\upload"));
                    fileList.add(fileInfo);
                    fileSort++;
                }
                map.put("attachList", fileList);
            }
            resultList.add(map);
            sort++;
        }
        return resultList;
    }


    /**
     * 数据补全转换
     *
     * @param originList 原始数据列表
     * @param startNum   起始查询数
     * @return 补全数据
     */
    private List<Map<String, Object>> completeCommentResult(List<BarCommentDto> originList, int startNum) {
        if (ObjectUtils.isEmpty(originList)) {
            return new ArrayList<>();
        }
        List<Map<String, Object>> resultList = new ArrayList<>(originList.size());

        int sort = startNum + 1;
        for (BarCommentDto record : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(record);
            map.put("sort", sort);
            User user = userDao.selectById(record.getCreateUser());
            map.put("userPic", user.getPortrait());
            map.put("userName", user.getName());
            map.put("statusName", BarStatusEnum.getNameByValue(record.getStatus()));
            map.put("cardStatusName", BarStatusEnum.getNameByValue(record.getCardStatus()));
//            if (plateMap.containsKey(record.getPlate())) {
//                Map<String,String> plateInfo = plateMap.get(record.getPlate());
//                map.put("plateName",plateInfo.get("name"));
//            }
            resultList.add(map);
            sort++;
        }
        return resultList;
    }
}
